﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ServiceModel;
using System.Threading;

using SIMA.Interfaces;
using SIMA.Core.Security;
using SIMA.Core.Enums;
using SIMA.Core.Data.Collection;
using SIMA.Entities;



namespace SIMA.Server.Services
{
    [ServiceBehavior(InstanceContextMode = InstanceContextMode.PerCall)]
    public class EstadoServer:ServerBase,IEstado
    {
        #region Fields

        private static List<IEstadoCallback> subscribers = new List<IEstadoCallback>();
        private static SmartContainer<T_C_Estado> estadosSmart;
        public ServiceHost host = null;

        #endregion

        #region Constructor

        public EstadoServer()
        {
            Init();
        }

        #endregion

        private void Init()
        {
            estadosSmart = new SmartContainer<T_C_Estado>(false, true);
            estadosSmart.Inserted += new EventHandler<SIMA.Core.EventArgs.InsertedEventArgs>(estadosSmart_Inserted);
            estadosSmart.Deleted += new EventHandler<SIMA.Core.EventArgs.DeletedEventArgs>(estadosSmart_Deleted);
            estadosSmart.Updated += new EventHandler<SIMA.Core.EventArgs.UpdatedEventArgs>(estadosSmart_Updated);
            estadosSmart.Failed += new EventHandler<SIMA.Core.EventArgs.FailedEventArgs>(estadosSmart_Failed);
        }

        void estadosSmart_Failed(object sender, SIMA.Core.EventArgs.FailedEventArgs e)
        {
            subscribers.ForEach(delegate(IEstadoCallback callback)
            {
                if (((ICommunicationObject)callback).State == CommunicationState.Opened)
                {
                    callback.OnError(e);
                }
                else
                {
                    subscribers.Remove(callback);
                }
            });
        }

        void estadosSmart_Updated(object sender, SIMA.Core.EventArgs.UpdatedEventArgs e)
        {
            subscribers.ForEach(delegate(IEstadoCallback callback)
            {
                if (((ICommunicationObject)callback).State == CommunicationState.Opened)
                {
                    callback.OnUpdated(e);
                }
                else
                {
                    subscribers.Remove(callback);
                }
            });
        }

        void estadosSmart_Deleted(object sender, SIMA.Core.EventArgs.DeletedEventArgs e)
        {
            subscribers.ForEach(delegate(IEstadoCallback callback)
            {
                if (((ICommunicationObject)callback).State == CommunicationState.Opened)
                {
                    callback.OnDeleted(e);
                }
                else
                {
                    subscribers.Remove(callback);
                }
            });
        }

        void estadosSmart_Inserted(object sender, SIMA.Core.EventArgs.InsertedEventArgs e)
        {
            subscribers.ForEach(delegate(IEstadoCallback callback)
            {
                if (((ICommunicationObject)callback).State == CommunicationState.Opened)
                {
                    callback.OnInserted(e);
                }
                else
                {
                    subscribers.Remove(callback);
                }
            });
        }

        public override void Connect()
        {
            using (ServiceHost host = new ServiceHost(typeof(EstadoServer), new Uri("net.tcp://192.168.1.33:18502")))
            {
                host.AddServiceEndpoint(typeof(IEstado), new NetTcpBinding(), "IEstadoSubscription");
                try
                {
                    host.Open();
                    Thread.Sleep(500);
                    Console.WriteLine("Iniciado el servicio de manejo de estado ... OK");
                }
                catch (Exception ex)
                {
                    Console.WriteLine(ex.Message);
                }
            }
        }

        #region Miembros de IEstado

        public void InsertEstado(SIMA.Entities.T_C_Estado estado)
        {
            estadosSmart.Add(estado);
        }

        public void UpdateEstado(SIMA.Entities.T_C_Estado estadoToUpdate, SIMA.Entities.T_C_Estado estadoUpdated)
        {
            estadosSmart.Update(estadoToUpdate, estadoUpdated);
        }

        public void DeleteEstado(SIMA.Entities.T_C_Estado estado)
        {
            estadosSmart.Remove(estado);
        }

        public void SelectSpecilized(string query, SIMA.Core.Enums.CommandType queryType, Profile perfil)
        {
            List<T_C_Estado> tmpEstados = estadosSmart[query, queryType];
            subscribers.ForEach(delegate(IEstadoCallback callback)
            {
                if (((ICommunicationObject)callback).State == CommunicationState.Opened)
                {
                    callback.OnSelected(tmpEstados);
                }
                else
                {
                    subscribers.Remove(callback);
                }
            });
        }

        
        public bool Subscribe()
        {
            try
            {
                IEstadoCallback callback = OperationContext.Current.GetCallbackChannel<IEstadoCallback>();
                if (!subscribers.Contains(callback))
                {
                    subscribers.Add(callback);
                }
                return true;
            }
            catch
            {
                return false;
            }
        }

        public bool Unsubscribe()
        {
            try
            {
                IEstadoCallback callback = OperationContext.Current.GetCallbackChannel<IEstadoCallback>();
                if (subscribers.Contains(callback))
                {
                    subscribers.Remove(callback);
                }
                return true;
            }
            catch
            {
                return false;
            }
        }

        #endregion
    }
}
